package com.hqd.jjvm.instructions.math;

import com.hqd.jjvm.instructions.AbstractInstruction;
import com.hqd.jjvm.instructions.InstructionType;
import com.hqd.jjvm.rtda.JThread;

public class MathInstruction extends AbstractInstruction {


    public MathInstruction(JThread jThread) {
        super(jThread);
    }

    @Override
    public void execute(InstructionType instructionType) {
        switch (instructionType) {
            case IADD: {
                int num1 = popOperandStackIntVal();
                int num2 = popOperandStackIntVal();
                pushOperandStackVal(num2 + num1);
                break;
            }
            case LADD: {
                long num1 = popOperandStackLongVal();
                long num2 = popOperandStackLongVal();
                pushOperandStackVal(num2 + num1);
                break;
            }
            case FADD: {
                float num1 = popOperandStackFloatVal();
                float num2 = popOperandStackFloatVal();
                pushOperandStackVal(num2 + num1);
                break;
            }
            case DADD: {
                double num1 = popOperandStackDoubleVal();
                double num2 = popOperandStackDoubleVal();
                pushOperandStackVal(num2 + num1);
                break;
            }
            case ISUB: {
                int num1 = popOperandStackIntVal();
                int num2 = popOperandStackIntVal();
                pushOperandStackVal(num2 - num1);
                break;
            }
            case LSUB: {
                long num1 = popOperandStackLongVal();
                long num2 = popOperandStackLongVal();
                pushOperandStackVal(num2 - num1);
                break;
            }
            case FSUB: {
                float num1 = popOperandStackFloatVal();
                float num2 = popOperandStackFloatVal();
                pushOperandStackVal(num2 - num1);
                break;
            }
            case DSUB: {
                double num1 = popOperandStackDoubleVal();
                double num2 = popOperandStackDoubleVal();
                pushOperandStackVal(num2 - num1);
                break;
            }
            case IMUL: {
                int num1 = popOperandStackIntVal();
                int num2 = popOperandStackIntVal();
                pushOperandStackVal(num2 * num1);
                break;
            }
            case LMUL: {
                long num1 = popOperandStackLongVal();
                long num2 = popOperandStackLongVal();
                pushOperandStackVal(num2 * num1);
                break;
            }
            case FMUL: {
                float num1 = popOperandStackFloatVal();
                float num2 = popOperandStackFloatVal();
                pushOperandStackVal(num2 * num1);
                break;
            }
            case DMUL: {
                double num1 = popOperandStackDoubleVal();
                double num2 = popOperandStackDoubleVal();
                pushOperandStackVal(num2 * num1);
                break;
            }
            case IDIV: {
                int num1 = popOperandStackIntVal();
                int num2 = popOperandStackIntVal();
                pushOperandStackVal(num2 / num1);
                break;
            }
            case LDIV: {
                long num1 = popOperandStackLongVal();
                long num2 = popOperandStackLongVal();
                pushOperandStackVal(num2 / num1);
                break;
            }
            case FDIV: {
                float num1 = popOperandStackFloatVal();
                float num2 = popOperandStackFloatVal();
                pushOperandStackVal(num2 / num1);
                break;
            }
            case DDIV: {
                double num1 = popOperandStackDoubleVal();
                double num2 = popOperandStackDoubleVal();
                pushOperandStackVal(num2 / num1);
                break;
            }
            case IREM: {
                int num1 = popOperandStackIntVal();
                int num2 = popOperandStackIntVal();
                pushOperandStackVal(num2 % num1);
                break;
            }
            case LREM: {
                long num1 = popOperandStackLongVal();
                long num2 = popOperandStackLongVal();
                pushOperandStackVal(num2 % num1);
                break;
            }
            case FREM: {
                float num1 = popOperandStackFloatVal();
                float num2 = popOperandStackFloatVal();
                pushOperandStackVal(num2 % num1);
                break;
            }
            case DREM: {
                double num1 = popOperandStackDoubleVal();
                double num2 = popOperandStackDoubleVal();
                pushOperandStackVal(num2 % num1);
                break;
            }
            case INEG: {
                int num = popOperandStackIntVal();
                pushOperandStackVal(-num);
                break;
            }
            case LNEG: {
                long num = popOperandStackLongVal();
                pushOperandStackVal(-num);
                break;
            }
            case FNEG: {
                float num = popOperandStackFloatVal();
                pushOperandStackVal(-num);
                break;
            }
            case DNEG: {
                double num = popOperandStackDoubleVal();
                pushOperandStackVal(-num);
                break;
            }
            case ISHL: {
                int num2 = popOperandStackIntVal();
                int num1 = popOperandStackIntVal();
                pushOperandStackVal(num1 << num2);
                break;
            }
            case LSHL: {
                int num2 = popOperandStackIntVal();
                long num1 = popOperandStackLongVal();
                pushOperandStackVal(num1 << num2);
                break;
            }
            case ISHR: {
                int num2 = popOperandStackIntVal();
                int num1 = popOperandStackIntVal();
                pushOperandStackVal(num1 >> num2);
                break;
            }
            case LSHR: {
                int num2 = popOperandStackIntVal();
                long num1 = popOperandStackLongVal();
                pushOperandStackVal(num1 >> num2);
                break;
            }
            case IUSHR: {
                Integer num2 = Integer.parseUnsignedInt(popOperandStackIntVal().toString());
                Integer num1 = popOperandStackIntVal();
                pushOperandStackVal(num1 >> num2);
                break;
            }
            case LUSHR: {
                Integer num2 = Integer.parseUnsignedInt(popOperandStackIntVal().toString());
                Long num1 = popOperandStackLongVal();
                pushOperandStackVal(num1 >> num2);
                break;
            }
            case IAND: {
                int num1 = popOperandStackIntVal();
                int num2 = popOperandStackIntVal();
                pushOperandStackVal(num2 & num1);
                break;
            }
            case LAND: {
                long num1 = popOperandStackLongVal();
                long num2 = popOperandStackLongVal();
                pushOperandStackVal(num2 & num1);
                break;
            }
            case IOR: {
                int num1 = popOperandStackIntVal();
                int num2 = popOperandStackIntVal();
                pushOperandStackVal(num2 | num1);
                break;
            }
            case LOR: {
                long num1 = popOperandStackLongVal();
                long num2 = popOperandStackLongVal();
                pushOperandStackVal(num2 | num1);
                break;
            }
            case IXOR: {
                int num1 = popOperandStackIntVal();
                int num2 = popOperandStackIntVal();
                pushOperandStackVal(num2 ^ num1);
                break;
            }
            case LXOR: {
                long num1 = popOperandStackLongVal();
                long num2 = popOperandStackLongVal();
                pushOperandStackVal(num2 ^ num1);
                break;
            }
            case IINC: {
                int index = parseAndReadValU1();
                byte num = (byte) parseAndReadValU1().intValue();
                num += getLocalVarsIntVal(index);
                setLocalVarsIntVal(index, num);
                break;
            }
        }
    }
}
